home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
BBS-Archive
/
DiskUtil
/
Crunch
/
XFH.lha
/
XFH
/
SRC
/
CFS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-24
|
32KB
|
1,158 lines
/* CFS.c - main packet loop.
Copyright (C) 1991, 1992, 1993, 1994 Kristian Nielsen.
This file is part of XFH, the compressing file system handler.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This file replaces the startup code! Make sure the object file
* corresponding to this source is linked into the head of the final
* executeable.
*/
#include "CFS.h"
#include <exec/ports.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <clib/alib_protos.h>
#include <string.h>
#include <stdarg.h>
#include <dossupport.h>
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
char Version[] = "$VER: XFH-Handler " VERSION " " __AMIGADATE__ "";
char Copyright[] = "$COPYRIGHT: Copyright (C) 1991, 1992, 1993, 1994 Kristian Nielsen";
/**************************************************************************
* *
* Handler entry point. *
* *
* Do initialisation and allocation, then enter main loop after returning *
* our initial packet. *
* *
**************************************************************************/
LONG __saveds NotReallyMain(void)
{
glb glob;
struct DosPacket *pkt;
int ret=0;
struct FileLock *parent;
void handle_packet(glb glob, struct DosPacket *pkt);
SysBase=*(struct ExecBase **)4L;
if ((glob=AllocMem(sizeof(struct glob),MEMF_CLEAR))==NULL) return(100);
glob->ioerr=ERROR_ACTION_NOT_KNOWN; /* Default error code. */
debug (("XFH/CFS compressing file system handler v" VERSION ".\n"
"Copyright (C) 1991,1992,1993 Kristian Nielsen.\n"));
debug (("Starting handler with task at 0x%lx.\n",FindTask(0L)));
glob->dosport=&(glob->myproc=(struct Process *)(glob->mytask=FindTask(0L)))->pr_MsgPort;
pkt=getpkt(glob);
glob->devnode=(struct DeviceNode *)b2c(pkt->dp_Arg3);
if (glob->devnode->dn_Name==NULL)
{
debug (("Error: NULL device name - exiting.\n"));
glob->ioerr=ERROR_INVALID_COMPONENT_NAME;
returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
goto exitthis;
}
if ((glob->devname=copybstr(glob->devnode->dn_Name))==NULL)
{
debug (("Error copying device name - exiting.\n"));
OUTOFMEM;
returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
goto exitthis;
}
if (glob->devname[0]=='\0')
{
debug (("Error: Empty device name - exiting.\n"));
glob->ioerr=ERROR_INVALID_COMPONENT_NAME;
returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
goto exitthis;
}
debug (("Using device name '%s'.\n",glob->devname));
glob->bcplstartup=glob->devnode->dn_Startup;
if ((glob->ioport=CreatePort(NULL,0L))==NULL)
{
OUTOFMEM;
returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug (("Error creating message port - exiting.\n"));
goto exitthis;
}
if ((glob->DOSBase=OpenLibrary("dos.library",0L))==NULL)
{
glob->ioerr=ERROR_INVALID_RESIDENT_LIBRARY;
returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
debug (("Error opening dos.library - exiting.\n"));
ret=100;
goto exitthis;
}
DOSBase=glob->DOSBase;
/* Set primary options (from S:.xfhrc.<unit>, if available). */
if (!InitOptions(glob))
{
returnpkt (pkt,DOSFALSE,ERROR_BAD_TEMPLATE,glob);
debug (("Error setting primary options - exiting.\n"));
ret=100;
goto exitthis;
}
if (!InitXpk(glob))
{
returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
debug (("Error initialising Xpk routines - exiting.\n"));
ret=100;
goto exitthis;
}
debug (("Using '%s' as root directory...\n",glob->xRootName));
glob->xprocid=DoDeviceProc( (LONG *)&glob->xrootlock,glob->xRootName,glob);
if (!glob->xprocid)
{
glob->xrootlock=0L; /* Don't xUnLock() */
returnpkt (pkt,DOSFALSE,ERROR_OBJECT_NOT_FOUND,glob);
ret=100;
debug (("Error doing DeviceProc(%s) - exiting.\n",glob->xRootName));
goto exitthis;
}
glob->xrootlock=b2c(glob->xrootlock);
debug (("DeviceProc(%s) returned: %lx %lx\n",glob->xRootName,
glob->xprocid,glob->xrootlock));
glob->xrootlock=xLock(glob,glob->xrootlock,glob->xRootName,ACCESS_READ);
if (glob->xrootlock==NULL)
{
returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug (("Error obtaining xrootlock: %ld - exiting.\n",glob->ioerr,
glob->xRootName));
goto exitthis;
}
debug (("Obtained xrootlock: %lx\n",glob->xrootlock ));
if (!SetOptionsFromFile(glob,glob->xrootlock,ALTOPTIONPATH))
{
returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug (("Error setting secondary options.\n"));
goto exitthis;
}
if (!xInfo(glob, glob->xrootlock,&glob->infodata))
{
returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug (("Error obtaining disk info: %ld\n",glob->ioerr));
goto exitthis;
}
glob->bytesperblock=glob->infodata.id_BytesPerBlock;
if (parent=xParentDir(glob,glob->xrootlock)) xUnLock(glob,parent);
if (!xExamine(glob,glob->xrootlock,&glob->fib1))
{
returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug (("Error finding name for volume: %ld\n",glob->ioerr));
goto exitthis;
}
if (!(glob->rootlock=makerootlockdayone(glob)))
{
returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug (("Error creating rootlock: %ld - exiting.\n",glob->ioerr));
goto exitthis;
}
if (!createvolnode(glob, parent == NULL, &glob->fib1))
{
returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug (("Error creating volume node - exiting.\n"));
goto exitthis;
}
if (!InitArexx(glob))
{
returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug (("Error initialising AREXX stuff.\n"));
goto exitthis;
}
if (!UpdateXFHNode(glob))
{
debug (("Error initialising XFHNode.\n"));
/* Carry on... */
}
/* Handler opened succesfully. Patch in task address so that we will
* stay in control for all future references.
*/
glob->devnode->dn_Task=glob->dosport;
debug (("1: Packet type received: %lx\n",pkt->dp_Type));
returnpkt (pkt,DOSTRUE,0L,glob);
glob->opencnt=0; /* Just for good measure... */
/* Ready to go for the main loop.
* Lets pray that we get no new messages before the initial ReplyPkt()
* (otherwise we may loose the signal for the message port).
*/
for (glob->done=FALSE; !glob->done;)
{
ULONG signals=Wait(arexxsigmask(glob)|getpktsigmask(glob)|guisigmask(glob));
if (signals&arexxsigmask(glob)) checkarexxmsg(glob);
if (signals&guisigmask(glob))
if (!UpdateXFHNode(glob))
debug (("Error during UpdateXFHNode().\n"));
if (signals&getpktsigmask(glob))
while (!glob->done&&(pkt=checkpkt(glob)))
handle_packet (glob,pkt);
}
exitthis:
debug (("CFS exiting...\n"));
CleanupArexx (glob);
if (glob->volnode) freevolnode (glob);
if (glob->rootlock) CFSUnLock (glob,glob->rootlock);
CleanupXpk (glob);
CleanupOptions (glob);
if (glob->ioport) DeletePort (glob->ioport);
if (glob->devname) freestr (glob->devname);
/*
* Unload the code. This is mostly to serve the ACTION_DIE packet.
* Useful for debugging (otherwise countless copies might end up in memory.
* It is rather ugly, however, and propably not really useful.
*/
Forbid();
UnLoadSeg (glob->devnode->dn_SegList);
glob->devnode->dn_SegList=NULL;
if (glob->DOSBase) CloseLibrary(glob->DOSBase);
FreeMem (glob,sizeof(struct glob));
return ret;
}
#ifndef ACTION_GET_DISK_FSSM
#define ACTION_GET_DISK_FSSM 4201
#endif
void handle_packet(glb glob,struct DosPacket *pkt)
{
glob->ioerr=0L;
switch(pkt->dp_Type)
{
case ACTION_LOCATE_OBJECT:
{
struct FileLock *mylock;
struct CFSLock *mycfslock;
debug (("ACTION_LOCATE_OBJECT(%lx,\"%s\",%ld)",
pkt->dp_Arg1,
bstr2c(pkt->dp_Arg2,glob->debugbuf1),
pkt->dp_Arg3));
mylock=b2c(pkt->dp_Arg1);
mycfslock=mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock;
mycfslock=CFSLock(glob,
mycfslock,
bstr2c(pkt->dp_Arg2,glob->pktstringbuf),
pkt->dp_Arg3);
if (mycfslock)
if (mylock=CreateFileLock(glob,mycfslock)) glob->opencnt++;
else
{
LONG saveioerr;
saveioerr=glob->ioerr;
CFSUnLock(glob, mycfslock);
glob->ioerr=saveioerr;
}
else mylock=NULL;
debug (("=%lx\n",c2b(mylock)));
returnpkt (pkt,c2b(mylock),glob->ioerr,glob);
break;
}
case ACTION_COPY_DIR:
{
struct FileLock *mylock;
struct CFSLock *mycfslock;
debug (("ACTION_COPY_DIR(%lx)",pkt->dp_Arg1));
mylock=b2c(pkt->dp_Arg1);
mycfslock=mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock;
if (mycfslock=CFSDupLock(glob,mycfslock))
{
if (mylock=CreateFileLock(glob, mycfslock )) glob->opencnt++;
else
{
LONG saveioerr;
saveioerr=glob->ioerr;
CFSUnLock(glob,mycfslock);
glob->ioerr=saveioerr;
}
}
else mylock=NULL;
debug (("=%lx\n",c2b(mylock)));
returnpkt (pkt, c2b(mylock), glob->ioerr, glob);
break;
}
case ACTION_PARENT:
{
struct FileLock *mylock;
struct CFSLock *mycfslock;
debug (("ACTION_PARENT(%lx)",pkt->dp_Arg1));
mylock=b2c(pkt->dp_Arg1);
mycfslock=mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock;
if (mycfslock=CFSParentDir(glob,mycfslock))
{
if (mylock=CreateFileLock(glob,mycfslock)) glob->opencnt++;
else
{
LONG saveioerr;
saveioerr=glob->ioerr;
CFSUnLock(glob, mycfslock);
glob->ioerr=saveioerr;
}
}
else mylock=NULL;
debug (("=%lx\n",c2b(mylock)));
returnpkt (pkt, c2b(mylock), glob->ioerr, glob);
break;
}
case ACTION_FREE_LOCK:
{
BOOL err;
struct FileLock *mylock;
debug (("ACTION_FREE_LOCK(%lx)\n",pkt->dp_Arg1));
mylock=b2c(pkt->dp_Arg1);
if (mylock)
{
err=CFSUnLock(glob,(void *)mylock->fl_Key);
if (err)
{
dfree(mylock);
glob->opencnt--;
}
}
else err=ERROR_OBJECT_WRONG_TYPE;
returnpkt (pkt,err,glob->ioerr,glob);
break;
}
/* ToDo: Handle NULL locks correct (but what is correct?)
* Now, a NULL lock is equal to out root lock.
*/
case ACTION_SAME_LOCK:
{
struct FileLock *fl1,*fl2;
BOOL res;
fl1=b2c(pkt->dp_Arg1);
fl2=b2c(pkt->dp_Arg2);
debug (("ACTION_SAME_LOCK(%lx,%lx)",fl1,fl2));
/* ToDo: This bit tests that both locks belong to us - this
* is probably bogus.
*/
if ((fl1!=NULL)&&(fl1->fl_Task!=glob->dosport)) res=FALSE;
else
if ((fl2!=NULL)&&(fl2->fl_Task!=glob->dosport)) res=FALSE;
else
{
struct CFSLock *f1,*f2;
f1=fl1?(struct CFSLock *)fl1->fl_Key:glob->rootlock;
f2=fl2?(struct CFSLock *)fl2->fl_Key:glob->rootlock;
res=CFSSameLock(glob,f1,f2);
}
debug (("=%ld\n",res));
/* ToDo: DOCS mention error code in case of zero return.
* Not currently implemented.
*/
returnpkt (pkt,res,glob->ioerr,glob);
break;
}
case ACTION_FINDINPUT: /* (filehandle, lock, name)->BOOL */
case ACTION_FINDOUTPUT:
case ACTION_FINDUPDATE:
{
struct FileHandle *fh;
struct CFSFH *cfsfh;
char *name;
struct FileLock *parentlock;
struct CFSLock *cfsparentlock;
debug (("%s(%lx,%lx,\"%s\")\n",
pkt->dp_Type==ACTION_FINDINPUT ?"ACTION_FINDINPUT":
pkt->dp_Type==ACTION_FINDOUTPUT?"ACTION_FINDOUTPUT":
"ACTION_FINDUPDATE",
pkt->dp_Arg1,pkt->dp_Arg2,
bstr2c(pkt->dp_Arg3,glob->debugbuf1)));
fh=b2c(pkt->dp_Arg1);
parentlock=b2c(pkt->dp_Arg2);
cfsparentlock=parentlock?(struct CFSLock *)parentlock->fl_Key:glob->rootlock;
name=bstr2c(pkt->dp_Arg3, glob->pktstringbuf);
cfsfh=CFSOpen(glob,cfsparentlock,name,pkt->dp_Type);
debug (("(=%lx)\n",cfsfh));
if (cfsfh)
{
glob->opencnt++;
fh->fh_Arg1=c2b(cfsfh);
returnpkt (pkt,DOSTRUE,glob->ioerr,glob);
}
else returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
break;
}
case ACTION_READ: /* (fh->arg1, buf, len)->actlen */
{
struct CFSFH *cfsfh;
LONG len;
void *buf;
debug (("ACTION_READ(%lx,%lx,%ld)\n",
pkt->dp_Arg1,pkt->dp_Arg2,pkt->dp_Arg3));
cfsfh=b2c(pkt->dp_Arg1);
buf=(void *)pkt->dp_Arg2;
len=pkt->dp_Arg3;
len=CFSRead(glob, cfsfh, buf, len);
returnpkt (pkt, len, glob->ioerr, glob);
break;
}
case ACTION_WRITE: /* (fh->arg1, buf, len)->actlen */
{
struct CFSFH *cfsfh;
LONG len;
void *buf;
debug (("ACTION_WRITE(%lx,%lx,%ld)\n",
pkt->dp_Arg1,pkt->dp_Arg2,pkt->dp_Arg3));
cfsfh=b2c(pkt->dp_Arg1);
buf=(void *)pkt->dp_Arg2;
len=pkt->dp_Arg3;
len=CFSWrite(glob, cfsfh, buf, len);
debug (("ACTION_WRITE returns %ld %ld.\n",len, glob->ioerr));
returnpkt (pkt, len, glob->ioerr, glob);
break;
}
case ACTION_SEEK: /* (fh->arg1, pos, offset)->actlen */
{
struct CFSFH *cfsfh;
LONG pos;
LONG offset;
debug (("ACTION_SEEK(%lx,%lx,%ld)\n",
pkt->dp_Arg1,pkt->dp_Arg2,pkt->dp_Arg3));
cfsfh=b2c(pkt->dp_Arg1);
pos=pkt->dp_Arg2;
offset=pkt->dp_Arg3;
pos=CFSSeek(glob, cfsfh, pos, offset);
returnpkt (pkt, pos, glob->ioerr, glob);
break;
}
case ACTION_END: /* (fh->arg1) -> BOOL */
{
struct CFSFH *cfsfh;
BOOL res;
cfsfh=b2c(pkt->dp_Arg1);
debug (("ACTION_END(%lx)\n",cfsfh));
res=CFSClose( glob, cfsfh );
if (res ) glob->opencnt--;
debug (("Closing file - still %ld files open.\n",glob->opencnt));
returnpkt (pkt,res,pkt->dp_Res2,glob);
break;
}
case ACTION_DIE:
debug (("ACTION_DIE()\n"));
Forbid();
if (!glob->opencnt)
{
glob->done=TRUE;
returnpkt (pkt,DOSTRUE,pkt->dp_Res2,glob);
glob->devnode->dn_Task=NULL;
debug (("No open files - Handler exiting.\n"));
}
else
{
returnpkt (pkt,DOSFALSE,ERROR_OBJECT_IN_USE,glob);
debug (("Cannot end yet - still %ld open files.\n",glob->opencnt));
}
Permit();
break;
case ACTION_EXAMINE_OBJECT:
{
struct FileInfoBlock *fib;
struct FileLock *mylock;
BOOL err;
debug (("ACTION_EXAMINE_OBJECT(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
mylock=b2c(pkt->dp_Arg1);
fib=b2c(pkt->dp_Arg2);
err=CFSExamine(glob,mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,fib);
debug (("NAME: %s DirEntryType: %ld err: %ld\n",
fib->fib_FileName, fib->fib_DirEntryType,err));
cstr2binplace(&fib->fib_FileName[0]);
cstr2binplace(&fib->fib_Comment[0]);
returnpkt (pkt,err,glob->ioerr,glob);
break;
}
case ACTION_EXAMINE_NEXT:
{
struct FileInfoBlock *fib;
struct FileLock *mylock;
BOOL err;
debug (("ACTION_EXAMINE_NEXT(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
mylock=b2c(pkt->dp_Arg1);
fib=b2c(pkt->dp_Arg2);
bstr2cinplace (&fib->fib_FileName[0]);
safebstr2cinplace (&fib->fib_Comment[0],80);
err=CFSExamineNext(glob,
mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
fib);
debug (("NAME: %s DirEntryType: %ld err: %ld\n",
fib->fib_FileName, fib->fib_DirEntryType,err));
cstr2binplace (&fib->fib_FileName[0]);
cstr2binplace (&fib->fib_Comment[0]);
returnpkt (pkt,err,glob->ioerr,glob);
break;
}
case ACTION_CREATE_DIR:
{ /* (parentlock, name) -> lock */
struct FileLock *mylock;
struct CFSLock *lock;
debug (("ACTION_CREATE_DIR(%lx,\"%s\") ",
pkt->dp_Arg1,bstr2c(pkt->dp_Arg2,glob->debugbuf1)));
mylock=b2c(pkt->dp_Arg1);
lock=CFSCreateDir(glob,
mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
bstr2c(pkt->dp_Arg2,glob->pktstringbuf));
if (lock)
{
if (mylock=CreateFileLock(glob,lock)) glob->opencnt++;
else
{
LONG saveioerr;
saveioerr=glob->ioerr;
CFSUnLock (glob,lock);
glob->ioerr=saveioerr;
}
}
else mylock=NULL;
debug (("= %lx\n",mylock));
returnpkt (pkt, c2b(mylock), glob->ioerr, glob);
break;
}
case ACTION_DELETE_OBJECT:
{ /* (parentlock, name) -> succes */
struct FileLock *mylock;
BOOL err;
debug (("ACTION_DELETE_OBJECT(%lx,\"%s\")\n", pkt->dp_Arg1,
bstr2c(pkt->dp_Arg2,glob->debugbuf1)));
mylock=b2c(pkt->dp_Arg1);
err=CFSDeleteFile(glob,
mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
bstr2c(pkt->dp_Arg2,glob->pktstringbuf));
if (!err) debug (("Error deleting file!\n"));
returnpkt (pkt, err, glob->ioerr, glob);
break;
}
case ACTION_RENAME_OBJECT:
{ /* (lock1,name1,lock2,name2) -> succes */
struct FileLock *mylock1, *mylock2;
BOOL err;
/* ToDo: Check that both locks belong to us? */
debug (("ACTION_RENAME_OBJECT(%lx,\"%s\", %lx,\"%s\")\n",pkt->dp_Arg1,
bstr2c(pkt->dp_Arg2,glob->debugbuf1),
pkt->dp_Arg3,
bstr2c(pkt->dp_Arg4,glob->debugbuf2)));
mylock1=b2c(pkt->dp_Arg1);
mylock2=b2c(pkt->dp_Arg3);
err=CFSRename(glob,
mylock1?(struct CFSLock *)mylock1->fl_Key:glob->rootlock,
bstr2c(pkt->dp_Arg2,glob->pktstringbuf),
mylock2?(struct CFSLock *)mylock2->fl_Key:glob->rootlock,
bstr2c(pkt->dp_Arg4,glob->pktstringbuf2));
if (!err) debug (("Error renaming file!\n"));
returnpkt (pkt, err, glob->ioerr, glob);
break;
}
case ACTION_SET_PROTECT:
{ /* (dummy, parentlock, name, bits) -> succes */
struct FileLock *mylock;
BOOL err;
debug (("ACTION_SET_PROTECT([%lx] %lx,\"%s\",%lx)\n",
pkt->dp_Arg1,pkt->dp_Arg2,
bstr2c(pkt->dp_Arg3,glob->debugbuf1),
pkt->dp_Arg4));
mylock=b2c(pkt->dp_Arg2);
err=CFSSetProtection(glob,
mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
bstr2c(pkt->dp_Arg3,glob->pktstringbuf),
pkt->dp_Arg4);
if (!err) debug (("Error changing protection bits!\n"));
returnpkt (pkt,err,glob->ioerr,glob);
break;
}
case ACTION_SET_COMMENT:
{ /* (dummy, parentlock, name, comment) -> succes */
struct FileLock *mylock;
BOOL err;
debug (("ACTION_SET_COMMENT([%lx] %lx,\"%s\",\"%s\")\n",
pkt->dp_Arg1,pkt->dp_Arg2,
bstr2c(pkt->dp_Arg3,glob->debugbuf1),
bstr2c(pkt->dp_Arg4,glob->debugbuf2)));
mylock=b2c(pkt->dp_Arg2);
err=CFSSetComment(glob,
mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
bstr2c(pkt->dp_Arg3,glob->pktstringbuf),
bstr2c(pkt->dp_Arg4,glob->pktstringbuf2));
if (!err) debug (("Error changing file comment!\n"));
returnpkt (pkt,err,glob->ioerr,glob);
break;
}
case ACTION_SET_DATE:
{ /* (dummy, parentlock, name, datestamp) -> succes */
struct FileLock *mylock;
BOOL err;
debug (("ACTION_SET_DATE([%lx] %lx,\"%s\",%ld,%ld,%ld)\n",
pkt->dp_Arg1,pkt->dp_Arg2,
bstr2c(pkt->dp_Arg3,glob->debugbuf1),
((struct DateStamp *)(pkt->dp_Arg4))->ds_Days,
((struct DateStamp *)(pkt->dp_Arg4))->ds_Minute,
((struct DateStamp *)(pkt->dp_Arg4))->ds_Tick));
mylock=b2c(pkt->dp_Arg2);
err=CFSSetDate(glob,
mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
bstr2c(pkt->dp_Arg3,glob->pktstringbuf),
(struct DateStamp *)pkt->dp_Arg4);
if (!err) debug (("Error changing objects date!\n"));
returnpkt (pkt, err, glob->ioerr, glob);
break;
}
case ACTION_DISK_INFO:
/* (infodata)=BOOL */
debug (("ACTION_DISK_INFO(%lx)\n",pkt->dp_Arg1));
returnpkt (pkt,diskinfo(glob,b2c(pkt->dp_Arg1)),0L,glob);
break;
case ACTION_INFO:
/* (lock,infodata)=BOOL */
debug (("ACTION_INFO(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
returnpkt (pkt,diskinfo(glob,b2c(pkt->dp_Arg2)),0L,glob);
break;
case ACTION_RENAME_DISK:
{ /* (BCPLNAME)=BOOL */
BOOL res;
debug (("ACTION_RENAME_DISK(%s)\n",
bstr2c(pkt->dp_Arg1,glob->debugbuf1)));
res=SetOptionPermanent(glob, "VOLUMENAME",
bstr2c(pkt->dp_Arg1,glob->pktstringbuf));
if (!res) debug (("Error during relabel: %ld.\n",glob->ioerr));
returnpkt (pkt,res,glob->ioerr,glob);
break;
}
case ACTION_IS_FILESYSTEM:
debug (("ACTION_IS_FILESYSTEM\n"));
returnpkt (pkt,DOSTRUE,0L,glob);
break;
case ACTION_PARENT_FH:
{
struct FileLock *mylock;
struct CFSLock *mycfslock;
debug (("ACTION_PARENT_FH(%lx)",pkt->dp_Arg1));
if (mycfslock=CFSParentFH(glob,b2c(pkt->dp_Arg1)))
if (mylock=CreateFileLock(glob, mycfslock )) glob->opencnt++;
else
{
LONG saveioerr;
saveioerr=glob->ioerr;
CFSUnLock (glob,mycfslock);
glob->ioerr=saveioerr;
}
else mylock=NULL;
debug (("=%lx\n",c2b(mylock)));
returnpkt (pkt, c2b(mylock), glob->ioerr, glob);
break;
}
case ACTION_EXAMINE_FH:
{
struct FileInfoBlock *fib;
struct CFSFH *fh;
BOOL err;
debug (("ACTION_EXAMINE_FH(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
fh=b2c(pkt->dp_Arg1);
fib=b2c(pkt->dp_Arg2);
err=CFSExamineFH(glob, fh, fib);
debug (("NAME: %s DirEntryType: %ld err: %ld\n",
fib->fib_FileName, fib->fib_DirEntryType,err));
cstr2binplace (&fib->fib_FileName[0]);
cstr2binplace (&fib->fib_Comment[0]);
returnpkt (pkt,err,glob->ioerr,glob);
break;
}
case ACTION_MAKE_LINK:
{
struct FileLock *mylock;
BOOL succ;
debug (("ACTION_MAKE_LINK(%lx,\"%s\",%lx,%ld)\n",
pkt->dp_Arg1,bstr2c(pkt->dp_Arg2,glob->debugbuf1),
pkt->dp_Arg3,pkt->dp_Arg4));
mylock=b2c(pkt->dp_Arg1);
succ=CFSMakeLink(glob,
mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
bstr2c(pkt->dp_Arg2,glob->pktstringbuf),
pkt->dp_Arg3,pkt->dp_Arg4);
#ifdef DEBUG
if (!succ) debug (("Error making link!\n"));
#endif
returnpkt (pkt,succ,glob->ioerr,glob);
break;
}
case ACTION_READ_LINK:
{
struct FileLock *mylock;
BOOL succ;
debug (("ACTION_READ_LINK(%lx,\"%s\")\n",pkt->dp_Arg1,pkt->dp_Arg2));
mylock=b2c(pkt->dp_Arg1);
succ=CFSReadLink(glob,
mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
(char *)pkt->dp_Arg2,(char *)pkt->dp_Arg3,pkt->dp_Arg4);
#ifdef DEBUG
if (succ) debug (("ReadLink: \"%s\"\n",pkt->dp_Arg3));
#endif
returnpkt (pkt,succ,glob->ioerr,glob);
break;
}
case ACTION_GET_DISK_FSSM:
returnpkt (pkt,DOSFALSE,ERROR_OBJECT_WRONG_TYPE,glob);
break;
default:
debug (("Unknown packet received: %ld\n",pkt->dp_Type));
returnpkt (pkt,DOSFALSE,ERROR_ACTION_NOT_KNOWN,glob);
}
}
struct DosPacket *getpkt(glb glob)
{
struct Message *msg;
while (!(msg=GetMsg(glob->dosport))) WaitPort(glob->dosport);
return (struct DosPacket *)msg->mn_Node.ln_Name;
}
ULONG getpktsigmask(glb glob)
{
return (ULONG)(1L<<glob->dosport->mp_SigBit);
}
struct DosPacket *checkpkt(glb glob)
{
struct Message *msg;
if (msg=GetMsg(glob->dosport)) return (struct DosPacket *)msg->mn_Node.ln_Name;
else return NULL;
}
void returnpkt (struct DosPacket *pkt,LONG res1,LONG res2,glb glob)
{
struct MsgPort *port;
struct Message *msg;
port=pkt->dp_Port;
msg=pkt->dp_Link;
msg->mn_Node.ln_Succ=msg->mn_Node.ln_Pred=NULL;
msg->mn_Node.ln_Name=(char *)pkt;
pkt->dp_Res1=res1;
pkt->dp_Res2=res2;
pkt->dp_Port=glob->dosport;
PutMsg(port,msg);
}
struct devprocmsg
{
struct Message msg;
void (*func)();
char *filedesc;
struct MsgPort *procid;
LONG res2;
};
void __asm CallDeviceProc(register __a0 struct devprocmsg *msg)
{
msg->procid=DeviceProc(msg->filedesc);
msg->res2=IoErr();
}
struct MsgPort *DoDeviceProc(LONG *res2,char *filedesc,glb glob)
{
struct devprocmsg msg,*msg2;
extern void DoDOSSeg();
struct MsgPort *procid;
msg.msg.mn_Node.ln_Succ=NULL;
msg.msg.mn_Node.ln_Pred=NULL;
msg.msg.mn_Node.ln_Name=NULL;
msg.msg.mn_Node.ln_Type=NT_MESSAGE;
msg.msg.mn_Node.ln_Pri=0;
msg.msg.mn_ReplyPort=glob->ioport;
msg.msg.mn_Length=sizeof(msg);
msg.func=(void (*)())CallDeviceProc;
msg.filedesc=filedesc;
if (!(procid=CreateProc("DoDOS",glob->mytask->tc_Node.ln_Pri,
(BPTR)((ULONG)DoDOSSeg>>2),4000L))) return 0L;
PutMsg(procid,(struct Message *)&msg);
do WaitPort(glob->ioport);
while (!(msg2=(struct devprocmsg *)GetMsg(glob->ioport)));
#ifdef DEBUG
if (msg2!=&msg) KPrintF ("ERROR: bogus return message: &msg=%lx msg2=%lx\n",&msg,msg2);
#endif
if (res2) *res2=msg2->res2;
return msg2->procid;
}
/* DOS device list locking.
* ToDo: Use correct 2.0 locking calls.
*/
static void MyLockDosList(glb glob)
{
Forbid();
}
static void MyUnlockDosList(glb glob)
{
Permit();
}
void addvolnode(glb glob,struct DeviceList *volnode)
{
struct DosInfo *dosinfo;
MyLockDosList(glob);
dosinfo=b2c( ((struct RootNode *)DOSBase->dl_Root)->rn_Info);
volnode->dl_Next=dosinfo->di_DevInfo;
dosinfo->di_DevInfo=c2b(volnode);
MyUnlockDosList(glob);
}
BOOL removevolnode(glb glob,struct DeviceList *volnode)
{
struct DosInfo *dosinfo;
BPTR *p;
/* ToDo: check for 2.0 device list locking. */
MyLockDosList(glob);
dosinfo=b2c( ((struct RootNode *)DOSBase->dl_Root)->rn_Info);
p=&dosinfo->di_DevInfo;
while(*p)
if (b2c(*p) == volnode)
{
*p=volnode->dl_Next;
MyUnlockDosList(glob);
return TRUE;
}
else p=&( ((struct DeviceList *)b2c(*p)) -> dl_Next);
MyUnlockDosList(glob);
/* Hey - we didn't find the node in the list! */
debug (("WARNING!:removevolnode(): volume node not found.\n"));
return FALSE;
}
/* Used to update the 'Startup' field in our device node (used in option
* 'KILLSTARTUP').
*/
void DevNode_Stuff_Startup_String(glb glob,BSTR value)
{
MyLockDosList(glob);
glob->devnode->dn_Startup=value;
MyUnlockDosList (glob);
}
/* NOTE: this function assumes properly dos device list locking!
* This function will fail if 'name' is NULL.
* NOTE: createvolnode(), below does this in it's own way.
*/
static BOOL stuffvolnamevolnode(glb glob,char *name)
{
UBYTE *bcplname,*oldbcplname;
/* NASTY BUG: It seems that the volume name is expected to be zero
* terminated even though it is a BSTR. Hence strlen()+2 in alloc. */
/* Check if user specified a volume name. */
if (name)
{
if (!(bcplname=dosalloc(strlen(name)+2)))
{
OUTOFMEM;
return FALSE;
}
/* Free any old name. */
oldbcplname=b2c(glob->volnode->dl_Name);
if (oldbcplname) dosfree (oldbcplname);
strcpy(bcplname,name);
cstr2binplace(bcplname);
glob->volnode->dl_Name=c2b(bcplname);
debug (("Using user suplied volumename '%s'.\n",bcplname+1));
return TRUE;
}
else
{
glob->ioerr=ERROR_INVALID_COMPONENT_NAME;
return FALSE;
}
}
/* This function creates our volumenode. The argument 'fixroot' is
* a hack, telling whether the volumename should be changed to prevent
* name-clashing with the volume name of the UFS.
*/
BOOL createvolnode(glb glob,BOOL fixroot,struct FileInfoBlock *fib)
{
UBYTE *bcplname;
if (!dalloc(glob->volnode)) return FALSE;
/* NASTY BUG: It seems that the volume name is expected to be zero
* terminated even though it is a BSTR. Hence strlen()+2 in alloc. */
/* Check if user specified a volume name. */
if (glob->uservolname)
{
if (!(bcplname=dosalloc(strlen(glob->uservolname)+2)))
{
dfree(glob->volnode);
return FALSE;
}
(void)strcpy(bcplname,glob->uservolname);
debug (("Using user suplied volumename '%s'.\n",bcplname));
}
else
{
if (!(bcplname=dosalloc(strlen(fib->fib_FileName)+2+
(fixroot?strlen(XROOTNAME)+1:0))))
{
dfree(glob->volnode);
return FALSE;
}
(void)strcat(strcpy(bcplname,fixroot?XROOTNAME "_":""),&fib->fib_FileName[0]);
debug (("Using default volume name '%s'.\n",bcplname));
}
glob->volnode->dl_Type=DLT_VOLUME;
glob->volnode->dl_Task=glob->dosport;
glob->volnode->dl_Lock=c2b(NULL);
glob->volnode->dl_VolumeDate=fib->fib_Date;
glob->volnode->dl_LockList=c2b(NULL);
glob->volnode->dl_DiskType=ID_DOS_DISK; /*Wonder what would be right*/
glob->volnode->dl_unused=0L;
cstr2binplace (bcplname);
glob->volnode->dl_Name=c2b(bcplname);
/* Check if user requested that we create a volume node. */
/* if (glob->createvolnode) */
addvolnode (glob,glob->volnode);
return TRUE;
}
/* Set the volume name in the volnode. */
BOOL SetVolumeNameVolNode(glb glob,char *name)
{
BOOL res;
MyLockDosList(glob);
res=stuffvolnamevolnode(glob,name);
MyUnlockDosList(glob);
return res;
}
BOOL freevolnode(glb glob)
{
/* Check if user requested that we create a volume node. */
/* if (glob->createvolnode)*/
if (!removevolnode(glob,glob->volnode)) return FALSE;
dosfree (b2c(glob->volnode->dl_Name));
dfree (glob->volnode);
return TRUE;
}
BOOL diskinfo(glb glob,struct InfoData *infodata)
{
if (!xInfo(glob,glob->xrootlock,infodata))
{
debug (("Error: diskinfo(): xInfo() returned zero (%ld).\n",glob->ioerr));
return DOSFALSE;
}
/* infodata->id_NumSoftErrors=0;*/
/* infodata->id_UnitNumber=glob->fsstartup ?*/
/* glob->fsstartup->fssm_Unit : 0;*/
/* infodata->id_DiskState=ID_VALIDATED;*/
/* infodata->id_NumBlocks=1;*/
/* infodata->id_NumBlocksUsed=1;*/
/* infodata->id_BytesPerBlock=1;*/
/* infodata->id_DiskType=ID_DOS_DISK;*/
infodata->id_VolumeNode=c2b(glob->volnode);
infodata->id_InUse=glob->opencnt?1:0;
debug (("diskinfo(): U=%ld DS=%lx #=%ld #u=%ld #b=%ld IU=%ld.\n",
infodata->id_UnitNumber,infodata->id_DiskState,infodata->id_NumBlocks,
infodata->id_NumBlocksUsed,infodata->id_BytesPerBlock,
infodata->id_InUse));
return DOSTRUE;
}
UWORD PutChar[2] = {0x16C0,0x4E75};
/* dirty hack to avoid assembler part :-)
16C0: move.b d0,(a3)+
4E75: rts
*/
void SPrintF(char *Buffer,char *FormatString,...)
{
RawDoFmt (FormatString,(APTR)((LONG *)&FormatString+1L),(void *)PutChar,Buffer);
}
/* End of CFS.c */